Downloading the data

In [2]:
from google.colab import files
files.upload()
Upload widget is only available when the cell has been executed in the current browser session. Please rerun this cell to enable.
Saving kaggle.json to kaggle.json
Out[2]:
{'kaggle.json': b'{"username":"dharanipoojitha","key":"8a5a919b6d23ed7c797c31a53d8eecdd"}'}
In [3]:
!mkdir ~/.kaggle
!cp kaggle.json ~/.kaggle/
!chmod 600 ~/.kaggle/kaggle.json
In [4]:
!kaggle competitions download -c dogs-vs-cats
Downloading dogs-vs-cats.zip to /content
100% 809M/812M [00:09<00:00, 60.2MB/s]
100% 812M/812M [00:09<00:00, 92.5MB/s]
In [5]:
!unzip -qq dogs-vs-cats.zip
!unzip -qq train.zip

Copying images to training, validation, and test directories

In [6]:
import os, shutil, pathlib

original_dir = pathlib.Path("train")
new_base_dir = pathlib.Path("cats_vs_dogs")

def make_subset(subset_name, start_index, end_index):
    for category in ("cat", "dog"):
        dir = new_base_dir / subset_name / category
        os.makedirs(dir)
        fnames = [f"{category}.{i}.jpg" for i in range(start_index, end_index)]
        for fname in fnames:
            shutil.copyfile(src=original_dir / fname,
                            dst=dir / fname)
  1. Consider the Cats & Dogs example. Start initially with a training sample of 1000, a validation sample of 500, and a test sample of 500 (half the sample size as the sample Jupyter notebook on Canvas). Use any technique to reduce overfitting and improve performance in developing a network that you train from scratch. What performance did you achieve?

Let us train a model from scratch. The model 1 has a Training sample of 1000, a Validation sample of 500, and a Test sample of 500.

In [7]:
from tensorflow.keras.utils import image_dataset_from_directory


make_subset("train", start_index=0, end_index=1000)
make_subset("validation", start_index=1000, end_index=1500)
make_subset("test", start_index=1500, end_index=2000)

train_dataset = image_dataset_from_directory(
    new_base_dir / "train",
    image_size=(180, 180),
    batch_size=32)
validation_dataset = image_dataset_from_directory(
    new_base_dir / "validation",
    image_size=(180, 180),
    batch_size=32)
test_dataset = image_dataset_from_directory(
    new_base_dir / "test",
    image_size=(180, 180),
    batch_size=32)

import numpy as np
import tensorflow as tf
random_numbers = np.random.normal(size=(1000, 16))
dataset = tf.data.Dataset.from_tensor_slices(random_numbers)

for i, element in enumerate(dataset):
    print(element.shape)
    if i >= 2:
        break

batched_dataset = dataset.batch(32)
for i, element in enumerate(batched_dataset):
    print(element.shape)
    if i >= 2:
        break

reshaped_dataset = dataset.map(lambda x: tf.reshape(x, (4, 4)))
for i, element in enumerate(reshaped_dataset):
    print(element.shape)
    if i >= 2:
        break

for data_batch, labels_batch in train_dataset:
    print("data batch shape:", data_batch.shape)
    print("labels batch shape:", labels_batch.shape)
    break
Found 2000 files belonging to 2 classes.
Found 1000 files belonging to 2 classes.
Found 1000 files belonging to 2 classes.
(16,)
(16,)
(16,)
(32, 16)
(32, 16)
(32, 16)
(4, 4)
(4, 4)
(4, 4)
data batch shape: (32, 180, 180, 3)
labels batch shape: (32,)
In [8]:
from tensorflow import keras
from tensorflow.keras import layers
import matplotlib.pyplot as plt


data_augmentation = keras.Sequential(
    [
        layers.RandomFlip("horizontal"),
        layers.RandomRotation(0.1),
        layers.RandomZoom(0.2),
    ]
)

plt.figure(figsize=(10, 10))
for images, _ in train_dataset.take(1):
    for i in range(9):
        augmented_images = data_augmentation(images)
        ax = plt.subplot(3, 3, i + 1)
        plt.imshow(augmented_images[0].numpy().astype("uint8"))
        plt.axis("off")


inputs = keras.Input(shape=(180, 180, 3))
x = data_augmentation(inputs)
x = layers.Rescaling(1./255)(inputs)
x = layers.Conv2D(filters=32, kernel_size=3, activation="relu")(x)
x = layers.MaxPooling2D(pool_size=2)(x)
x = layers.Conv2D(filters=64, kernel_size=3, activation="relu")(x)
x = layers.MaxPooling2D(pool_size=2)(x)
x = layers.Conv2D(filters=128, kernel_size=3, activation="relu")(x)
x = layers.MaxPooling2D(pool_size=2)(x)
x = layers.Conv2D(filters=256, kernel_size=3, activation="relu")(x)
x = layers.MaxPooling2D(pool_size=2)(x)
x = layers.Conv2D(filters=256, kernel_size=3, activation="relu")(x)
x = layers.Flatten()(x)
outputs = layers.Dense(1, activation="sigmoid")(x)
model = keras.Model(inputs=inputs, outputs=outputs)
model.summary()


model.compile(loss="binary_crossentropy",
              optimizer="rmsprop",
              metrics=["accuracy"])


callbacks = [
    keras.callbacks.ModelCheckpoint(
        filepath="convnet_from_scratch.keras",
        save_best_only=True,
        monitor="val_loss")
]
history = model.fit(
    train_dataset,
    epochs=50,
    validation_data=validation_dataset,
    callbacks=callbacks)


test_model = keras.models.load_model("convnet_from_scratch.keras")
test_loss, test_acc = test_model.evaluate(test_dataset)
print(f"Test accuracy: {test_acc:.3f}")
Model: "functional_1"
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━┓
┃ Layer (type)                         ┃ Output Shape                ┃         Param # ┃
┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━┩
│ input_layer_1 (InputLayer)           │ (None, 180, 180, 3)         │               0 │
├──────────────────────────────────────┼─────────────────────────────┼─────────────────┤
│ rescaling (Rescaling)                │ (None, 180, 180, 3)         │               0 │
├──────────────────────────────────────┼─────────────────────────────┼─────────────────┤
│ conv2d (Conv2D)                      │ (None, 178, 178, 32)        │             896 │
├──────────────────────────────────────┼─────────────────────────────┼─────────────────┤
│ max_pooling2d (MaxPooling2D)         │ (None, 89, 89, 32)          │               0 │
├──────────────────────────────────────┼─────────────────────────────┼─────────────────┤
│ conv2d_1 (Conv2D)                    │ (None, 87, 87, 64)          │          18,496 │
├──────────────────────────────────────┼─────────────────────────────┼─────────────────┤
│ max_pooling2d_1 (MaxPooling2D)       │ (None, 43, 43, 64)          │               0 │
├──────────────────────────────────────┼─────────────────────────────┼─────────────────┤
│ conv2d_2 (Conv2D)                    │ (None, 41, 41, 128)         │          73,856 │
├──────────────────────────────────────┼─────────────────────────────┼─────────────────┤
│ max_pooling2d_2 (MaxPooling2D)       │ (None, 20, 20, 128)         │               0 │
├──────────────────────────────────────┼─────────────────────────────┼─────────────────┤
│ conv2d_3 (Conv2D)                    │ (None, 18, 18, 256)         │         295,168 │
├──────────────────────────────────────┼─────────────────────────────┼─────────────────┤
│ max_pooling2d_3 (MaxPooling2D)       │ (None, 9, 9, 256)           │               0 │
├──────────────────────────────────────┼─────────────────────────────┼─────────────────┤
│ conv2d_4 (Conv2D)                    │ (None, 7, 7, 256)           │         590,080 │
├──────────────────────────────────────┼─────────────────────────────┼─────────────────┤
│ flatten (Flatten)                    │ (None, 12544)               │               0 │
├──────────────────────────────────────┼─────────────────────────────┼─────────────────┤
│ dense (Dense)                        │ (None, 1)                   │          12,545 │
└──────────────────────────────────────┴─────────────────────────────┴─────────────────┘
 Total params: 991,041 (3.78 MB)
 Trainable params: 991,041 (3.78 MB)
 Non-trainable params: 0 (0.00 B)
Epoch 1/50
63/63 ━━━━━━━━━━━━━━━━━━━━ 18s 168ms/step - accuracy: 0.4879 - loss: 0.7983 - val_accuracy: 0.5000 - val_loss: 0.6928
Epoch 2/50
63/63 ━━━━━━━━━━━━━━━━━━━━ 3s 52ms/step - accuracy: 0.5183 - loss: 0.6937 - val_accuracy: 0.5000 - val_loss: 0.7191
Epoch 3/50
63/63 ━━━━━━━━━━━━━━━━━━━━ 5s 53ms/step - accuracy: 0.5117 - loss: 0.6950 - val_accuracy: 0.5450 - val_loss: 0.6823
Epoch 4/50
63/63 ━━━━━━━━━━━━━━━━━━━━ 8s 102ms/step - accuracy: 0.5639 - loss: 0.6777 - val_accuracy: 0.5650 - val_loss: 0.6707
Epoch 5/50
63/63 ━━━━━━━━━━━━━━━━━━━━ 7s 52ms/step - accuracy: 0.6207 - loss: 0.6344 - val_accuracy: 0.6650 - val_loss: 0.6364
Epoch 6/50
63/63 ━━━━━━━━━━━━━━━━━━━━ 7s 84ms/step - accuracy: 0.6728 - loss: 0.6343 - val_accuracy: 0.6370 - val_loss: 0.6479
Epoch 7/50
63/63 ━━━━━━━━━━━━━━━━━━━━ 8s 51ms/step - accuracy: 0.6889 - loss: 0.6052 - val_accuracy: 0.6240 - val_loss: 0.6903
Epoch 8/50
63/63 ━━━━━━━━━━━━━━━━━━━━ 6s 89ms/step - accuracy: 0.7225 - loss: 0.5634 - val_accuracy: 0.7020 - val_loss: 0.5764
Epoch 9/50
63/63 ━━━━━━━━━━━━━━━━━━━━ 8s 58ms/step - accuracy: 0.7469 - loss: 0.5118 - val_accuracy: 0.6370 - val_loss: 0.7865
Epoch 10/50
63/63 ━━━━━━━━━━━━━━━━━━━━ 6s 80ms/step - accuracy: 0.7490 - loss: 0.5311 - val_accuracy: 0.7050 - val_loss: 0.5587
Epoch 11/50
63/63 ━━━━━━━━━━━━━━━━━━━━ 5s 72ms/step - accuracy: 0.7719 - loss: 0.4785 - val_accuracy: 0.7010 - val_loss: 0.5701
Epoch 12/50
63/63 ━━━━━━━━━━━━━━━━━━━━ 3s 51ms/step - accuracy: 0.7946 - loss: 0.4269 - val_accuracy: 0.6980 - val_loss: 0.6614
Epoch 13/50
63/63 ━━━━━━━━━━━━━━━━━━━━ 3s 52ms/step - accuracy: 0.8319 - loss: 0.3848 - val_accuracy: 0.6740 - val_loss: 0.7369
Epoch 14/50
63/63 ━━━━━━━━━━━━━━━━━━━━ 6s 88ms/step - accuracy: 0.8512 - loss: 0.3417 - val_accuracy: 0.6990 - val_loss: 0.6296
Epoch 15/50
63/63 ━━━━━━━━━━━━━━━━━━━━ 8s 59ms/step - accuracy: 0.8912 - loss: 0.2583 - val_accuracy: 0.7140 - val_loss: 0.7621
Epoch 16/50
63/63 ━━━━━━━━━━━━━━━━━━━━ 7s 93ms/step - accuracy: 0.8979 - loss: 0.2473 - val_accuracy: 0.7250 - val_loss: 0.7721
Epoch 17/50
63/63 ━━━━━━━━━━━━━━━━━━━━ 4s 57ms/step - accuracy: 0.9231 - loss: 0.1806 - val_accuracy: 0.6820 - val_loss: 1.0768
Epoch 18/50
63/63 ━━━━━━━━━━━━━━━━━━━━ 5s 53ms/step - accuracy: 0.9286 - loss: 0.1723 - val_accuracy: 0.7320 - val_loss: 1.0399
Epoch 19/50
63/63 ━━━━━━━━━━━━━━━━━━━━ 8s 103ms/step - accuracy: 0.9522 - loss: 0.1136 - val_accuracy: 0.7050 - val_loss: 1.2337
Epoch 20/50
63/63 ━━━━━━━━━━━━━━━━━━━━ 3s 52ms/step - accuracy: 0.9668 - loss: 0.1011 - val_accuracy: 0.7080 - val_loss: 1.2973
Epoch 21/50
63/63 ━━━━━━━━━━━━━━━━━━━━ 5s 52ms/step - accuracy: 0.9586 - loss: 0.1113 - val_accuracy: 0.7290 - val_loss: 1.2266
Epoch 22/50
63/63 ━━━━━━━━━━━━━━━━━━━━ 4s 71ms/step - accuracy: 0.9739 - loss: 0.0663 - val_accuracy: 0.7100 - val_loss: 1.4523
Epoch 23/50
63/63 ━━━━━━━━━━━━━━━━━━━━ 5s 67ms/step - accuracy: 0.9704 - loss: 0.0674 - val_accuracy: 0.7100 - val_loss: 1.6233
Epoch 24/50
63/63 ━━━━━━━━━━━━━━━━━━━━ 4s 57ms/step - accuracy: 0.9801 - loss: 0.0689 - val_accuracy: 0.7260 - val_loss: 1.5360
Epoch 25/50
63/63 ━━━━━━━━━━━━━━━━━━━━ 5s 56ms/step - accuracy: 0.9713 - loss: 0.1040 - val_accuracy: 0.6980 - val_loss: 1.8070
Epoch 26/50
63/63 ━━━━━━━━━━━━━━━━━━━━ 5s 86ms/step - accuracy: 0.9869 - loss: 0.0413 - val_accuracy: 0.6810 - val_loss: 2.1662
Epoch 27/50
63/63 ━━━━━━━━━━━━━━━━━━━━ 8s 58ms/step - accuracy: 0.9813 - loss: 0.0596 - val_accuracy: 0.7160 - val_loss: 1.9012
Epoch 28/50
63/63 ━━━━━━━━━━━━━━━━━━━━ 4s 69ms/step - accuracy: 0.9841 - loss: 0.0507 - val_accuracy: 0.7040 - val_loss: 2.0670
Epoch 29/50
63/63 ━━━━━━━━━━━━━━━━━━━━ 5s 66ms/step - accuracy: 0.9819 - loss: 0.0441 - val_accuracy: 0.7260 - val_loss: 1.8001
Epoch 30/50
63/63 ━━━━━━━━━━━━━━━━━━━━ 4s 53ms/step - accuracy: 0.9961 - loss: 0.0132 - val_accuracy: 0.6970 - val_loss: 2.2206
Epoch 31/50
63/63 ━━━━━━━━━━━━━━━━━━━━ 3s 52ms/step - accuracy: 0.9852 - loss: 0.0573 - val_accuracy: 0.7090 - val_loss: 2.1233
Epoch 32/50
63/63 ━━━━━━━━━━━━━━━━━━━━ 5s 79ms/step - accuracy: 0.9740 - loss: 0.0889 - val_accuracy: 0.7020 - val_loss: 2.0830
Epoch 33/50
63/63 ━━━━━━━━━━━━━━━━━━━━ 4s 63ms/step - accuracy: 0.9947 - loss: 0.0308 - val_accuracy: 0.6850 - val_loss: 2.1733
Epoch 34/50
63/63 ━━━━━━━━━━━━━━━━━━━━ 5s 59ms/step - accuracy: 0.9947 - loss: 0.0230 - val_accuracy: 0.7040 - val_loss: 2.2599
Epoch 35/50
63/63 ━━━━━━━━━━━━━━━━━━━━ 7s 86ms/step - accuracy: 0.9900 - loss: 0.0293 - val_accuracy: 0.7150 - val_loss: 2.3724
Epoch 36/50
63/63 ━━━━━━━━━━━━━━━━━━━━ 4s 62ms/step - accuracy: 0.9845 - loss: 0.0595 - val_accuracy: 0.7300 - val_loss: 2.4565
Epoch 37/50
63/63 ━━━━━━━━━━━━━━━━━━━━ 3s 54ms/step - accuracy: 0.9858 - loss: 0.0554 - val_accuracy: 0.6960 - val_loss: 2.5770
Epoch 38/50
63/63 ━━━━━━━━━━━━━━━━━━━━ 4s 57ms/step - accuracy: 0.9926 - loss: 0.0336 - val_accuracy: 0.6960 - val_loss: 2.5435
Epoch 39/50
63/63 ━━━━━━━━━━━━━━━━━━━━ 7s 81ms/step - accuracy: 0.9915 - loss: 0.0344 - val_accuracy: 0.7090 - val_loss: 2.7056
Epoch 40/50
63/63 ━━━━━━━━━━━━━━━━━━━━ 8s 52ms/step - accuracy: 0.9979 - loss: 0.0135 - val_accuracy: 0.6920 - val_loss: 2.6403
Epoch 41/50
63/63 ━━━━━━━━━━━━━━━━━━━━ 7s 81ms/step - accuracy: 0.9831 - loss: 0.0548 - val_accuracy: 0.7200 - val_loss: 2.4621
Epoch 42/50
63/63 ━━━━━━━━━━━━━━━━━━━━ 8s 53ms/step - accuracy: 0.9894 - loss: 0.0618 - val_accuracy: 0.7190 - val_loss: 2.7350
Epoch 43/50
63/63 ━━━━━━━━━━━━━━━━━━━━ 6s 93ms/step - accuracy: 0.9913 - loss: 0.0399 - val_accuracy: 0.7080 - val_loss: 2.8345
Epoch 44/50
63/63 ━━━━━━━━━━━━━━━━━━━━ 8s 53ms/step - accuracy: 0.9919 - loss: 0.0377 - val_accuracy: 0.7090 - val_loss: 2.6473
Epoch 45/50
63/63 ━━━━━━━━━━━━━━━━━━━━ 7s 78ms/step - accuracy: 0.9946 - loss: 0.0239 - val_accuracy: 0.7000 - val_loss: 2.7864
Epoch 46/50
63/63 ━━━━━━━━━━━━━━━━━━━━ 4s 71ms/step - accuracy: 0.9897 - loss: 0.0310 - val_accuracy: 0.7070 - val_loss: 3.0391
Epoch 47/50
63/63 ━━━━━━━━━━━━━━━━━━━━ 3s 51ms/step - accuracy: 0.9917 - loss: 0.0314 - val_accuracy: 0.7020 - val_loss: 3.2215
Epoch 48/50
63/63 ━━━━━━━━━━━━━━━━━━━━ 3s 53ms/step - accuracy: 0.9842 - loss: 0.0529 - val_accuracy: 0.7390 - val_loss: 2.5755
Epoch 49/50
63/63 ━━━━━━━━━━━━━━━━━━━━ 7s 84ms/step - accuracy: 0.9799 - loss: 0.0524 - val_accuracy: 0.7050 - val_loss: 3.3300
Epoch 50/50
63/63 ━━━━━━━━━━━━━━━━━━━━ 9s 58ms/step - accuracy: 0.9915 - loss: 0.0348 - val_accuracy: 0.6860 - val_loss: 3.4859
32/32 ━━━━━━━━━━━━━━━━━━━━ 3s 63ms/step - accuracy: 0.6776 - loss: 0.6002
Test accuracy: 0.681
In [9]:
accuracy = history.history["accuracy"]
val_accuracy = history.history["val_accuracy"]
loss = history.history["loss"]
val_loss = history.history["val_loss"]
epochs = range(1, len(accuracy) + 1)
plt.plot(epochs, accuracy, "bo", label="Training accuracy")
plt.plot(epochs, val_accuracy, "b", label="Validation accuracy")
plt.title("Training and validation accuracy")
plt.legend()
plt.figure()
plt.plot(epochs, loss, "bo", label="Training loss")
plt.plot(epochs, val_loss, "b", label="Validation loss")
plt.title("Training and validation loss")
plt.legend()
plt.show()
  1. Increase your training sample size. You may pick any amount. Keep the validation and test samples the same as above. Optimize your network (again training from scratch). What performance did you achieve?

For the second model we are increasing training sample and keeping validation sample of 500, and a test sample of 500.

In [10]:
from tensorflow.keras.utils import image_dataset_from_directory


make_subset("train_2", start_index=0, end_index=3000)
make_subset("validation_2", start_index=3000, end_index=3500)
make_subset("test_2", start_index=3500, end_index=4000)

train_dataset = image_dataset_from_directory(
    new_base_dir / "train_2",
    image_size=(180, 180),
    batch_size=32)
validation_dataset = image_dataset_from_directory(
    new_base_dir / "validation_2",
    image_size=(180, 180),
    batch_size=32)
test_dataset = image_dataset_from_directory(
    new_base_dir / "test_2",
    image_size=(180, 180),
    batch_size=32)
Found 6000 files belonging to 2 classes.
Found 1000 files belonging to 2 classes.
Found 1000 files belonging to 2 classes.
In [13]:
from tensorflow import keras
from tensorflow.keras import layers
import matplotlib.pyplot as plt
from keras.callbacks import EarlyStopping
from keras import regularizers
# Define early_stopping_monitor
# used early stopping to stop optimization when it isn't helping any more.
early_stopping_monitor = EarlyStopping(patience=10)

data_augmentation = keras.Sequential(
    [
        layers.RandomFlip("horizontal"),
        layers.RandomRotation(0.1),
        layers.RandomZoom(0.2),
    ]
)

plt.figure(figsize=(10, 10))
for images, _ in train_dataset.take(1):
    for i in range(9):
        augmented_images = data_augmentation(images)
        ax = plt.subplot(3, 3, i + 1)
        plt.imshow(augmented_images[0].numpy().astype("uint8"))
        plt.axis("off")


inputs = keras.Input(shape=(180, 180, 3))
x = layers.Rescaling(1./255)(inputs)
x = layers.Conv2D(filters=32, kernel_size=3, activation="relu")(x)
x = layers.MaxPooling2D(pool_size=2)(x)
x = layers.Conv2D(filters=64, kernel_size=3, activation="relu")(x)
x = layers.MaxPooling2D(pool_size=2)(x)
x = layers.Conv2D(filters=128, kernel_size=3, activation="relu")(x)
x = layers.MaxPooling2D(pool_size=2)(x)
x = layers.Conv2D(filters=256, kernel_size=3, activation="relu")(x)
x = layers.MaxPooling2D(pool_size=2)(x)
x = layers.Conv2D(filters=256, kernel_size=3, activation="relu",kernel_regularizer = regularizers.l2(l2=0.01))(x)
x = layers.Flatten()(x)
x = layers.Dropout(0.5)(x)
outputs = layers.Dense(1, activation="sigmoid")(x)
model = keras.Model(inputs=inputs, outputs=outputs)
model.summary()


model.compile(loss="binary_crossentropy",
              optimizer=keras.optimizers.RMSprop(learning_rate=1e-3),
              metrics=["accuracy"])


callbacks = [
    keras.callbacks.ModelCheckpoint(
        filepath="convnet_from_scratch.keras",
        save_best_only=True,
        monitor="val_loss"), early_stopping_monitor
]
history = model.fit(
    train_dataset,
    epochs=50,
    validation_data=validation_dataset,
    callbacks=callbacks)

test_model = keras.models.load_model("convnet_from_scratch.keras")
test_loss, test_acc = test_model.evaluate(test_dataset)
print(f"Test accuracy: {test_acc:.3f}")
Model: "functional_5"
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━┓
┃ Layer (type)                         ┃ Output Shape                ┃         Param # ┃
┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━┩
│ input_layer_7 (InputLayer)           │ (None, 180, 180, 3)         │               0 │
├──────────────────────────────────────┼─────────────────────────────┼─────────────────┤
│ rescaling_3 (Rescaling)              │ (None, 180, 180, 3)         │               0 │
├──────────────────────────────────────┼─────────────────────────────┼─────────────────┤
│ conv2d_13 (Conv2D)                   │ (None, 178, 178, 32)        │             896 │
├──────────────────────────────────────┼─────────────────────────────┼─────────────────┤
│ max_pooling2d_12 (MaxPooling2D)      │ (None, 89, 89, 32)          │               0 │
├──────────────────────────────────────┼─────────────────────────────┼─────────────────┤
│ conv2d_14 (Conv2D)                   │ (None, 87, 87, 64)          │          18,496 │
├──────────────────────────────────────┼─────────────────────────────┼─────────────────┤
│ max_pooling2d_13 (MaxPooling2D)      │ (None, 43, 43, 64)          │               0 │
├──────────────────────────────────────┼─────────────────────────────┼─────────────────┤
│ conv2d_15 (Conv2D)                   │ (None, 41, 41, 128)         │          73,856 │
├──────────────────────────────────────┼─────────────────────────────┼─────────────────┤
│ max_pooling2d_14 (MaxPooling2D)      │ (None, 20, 20, 128)         │               0 │
├──────────────────────────────────────┼─────────────────────────────┼─────────────────┤
│ conv2d_16 (Conv2D)                   │ (None, 18, 18, 256)         │         295,168 │
├──────────────────────────────────────┼─────────────────────────────┼─────────────────┤
│ max_pooling2d_15 (MaxPooling2D)      │ (None, 9, 9, 256)           │               0 │
├──────────────────────────────────────┼─────────────────────────────┼─────────────────┤
│ conv2d_17 (Conv2D)                   │ (None, 7, 7, 256)           │         590,080 │
├──────────────────────────────────────┼─────────────────────────────┼─────────────────┤
│ flatten_1 (Flatten)                  │ (None, 12544)               │               0 │
├──────────────────────────────────────┼─────────────────────────────┼─────────────────┤
│ dropout (Dropout)                    │ (None, 12544)               │               0 │
├──────────────────────────────────────┼─────────────────────────────┼─────────────────┤
│ dense_1 (Dense)                      │ (None, 1)                   │          12,545 │
└──────────────────────────────────────┴─────────────────────────────┴─────────────────┘
 Total params: 991,041 (3.78 MB)
 Trainable params: 991,041 (3.78 MB)
 Non-trainable params: 0 (0.00 B)
Epoch 1/50
188/188 ━━━━━━━━━━━━━━━━━━━━ 20s 81ms/step - accuracy: 0.5150 - loss: 1.2166 - val_accuracy: 0.5960 - val_loss: 0.6718
Epoch 2/50
188/188 ━━━━━━━━━━━━━━━━━━━━ 10s 42ms/step - accuracy: 0.6040 - loss: 0.6689 - val_accuracy: 0.6120 - val_loss: 0.6713
Epoch 3/50
188/188 ━━━━━━━━━━━━━━━━━━━━ 11s 56ms/step - accuracy: 0.6495 - loss: 0.6408 - val_accuracy: 0.6970 - val_loss: 0.5784
Epoch 4/50
188/188 ━━━━━━━━━━━━━━━━━━━━ 10s 55ms/step - accuracy: 0.6754 - loss: 0.6129 - val_accuracy: 0.7180 - val_loss: 0.5548
Epoch 5/50
188/188 ━━━━━━━━━━━━━━━━━━━━ 9s 46ms/step - accuracy: 0.6951 - loss: 0.5812 - val_accuracy: 0.6950 - val_loss: 0.5716
Epoch 6/50
188/188 ━━━━━━━━━━━━━━━━━━━━ 11s 57ms/step - accuracy: 0.7407 - loss: 0.5373 - val_accuracy: 0.6990 - val_loss: 0.5829
Epoch 7/50
188/188 ━━━━━━━━━━━━━━━━━━━━ 8s 42ms/step - accuracy: 0.7546 - loss: 0.5210 - val_accuracy: 0.7160 - val_loss: 0.5793
Epoch 8/50
188/188 ━━━━━━━━━━━━━━━━━━━━ 11s 48ms/step - accuracy: 0.7693 - loss: 0.4892 - val_accuracy: 0.7420 - val_loss: 0.5401
Epoch 9/50
188/188 ━━━━━━━━━━━━━━━━━━━━ 12s 56ms/step - accuracy: 0.7814 - loss: 0.4681 - val_accuracy: 0.7980 - val_loss: 0.4411
Epoch 10/50
188/188 ━━━━━━━━━━━━━━━━━━━━ 9s 46ms/step - accuracy: 0.7971 - loss: 0.4541 - val_accuracy: 0.8000 - val_loss: 0.4479
Epoch 11/50
188/188 ━━━━━━━━━━━━━━━━━━━━ 10s 45ms/step - accuracy: 0.8149 - loss: 0.4262 - val_accuracy: 0.7540 - val_loss: 0.5874
Epoch 12/50
188/188 ━━━━━━━━━━━━━━━━━━━━ 13s 58ms/step - accuracy: 0.8309 - loss: 0.4019 - val_accuracy: 0.7750 - val_loss: 0.4997
Epoch 13/50
188/188 ━━━━━━━━━━━━━━━━━━━━ 10s 51ms/step - accuracy: 0.8397 - loss: 0.3919 - val_accuracy: 0.7910 - val_loss: 0.4734
Epoch 14/50
188/188 ━━━━━━━━━━━━━━━━━━━━ 10s 48ms/step - accuracy: 0.8451 - loss: 0.3708 - val_accuracy: 0.8470 - val_loss: 0.3971
Epoch 15/50
188/188 ━━━━━━━━━━━━━━━━━━━━ 12s 59ms/step - accuracy: 0.8597 - loss: 0.3412 - val_accuracy: 0.7520 - val_loss: 0.7066
Epoch 16/50
188/188 ━━━━━━━━━━━━━━━━━━━━ 9s 46ms/step - accuracy: 0.8688 - loss: 0.3320 - val_accuracy: 0.8210 - val_loss: 0.4748
Epoch 17/50
188/188 ━━━━━━━━━━━━━━━━━━━━ 10s 46ms/step - accuracy: 0.8804 - loss: 0.3105 - val_accuracy: 0.8450 - val_loss: 0.4051
Epoch 18/50
188/188 ━━━━━━━━━━━━━━━━━━━━ 11s 57ms/step - accuracy: 0.8977 - loss: 0.2840 - val_accuracy: 0.8350 - val_loss: 0.4304
Epoch 19/50
188/188 ━━━━━━━━━━━━━━━━━━━━ 8s 43ms/step - accuracy: 0.9009 - loss: 0.2639 - val_accuracy: 0.8160 - val_loss: 0.5621
Epoch 20/50
188/188 ━━━━━━━━━━━━━━━━━━━━ 11s 59ms/step - accuracy: 0.9064 - loss: 0.2471 - val_accuracy: 0.8210 - val_loss: 0.6066
Epoch 21/50
188/188 ━━━━━━━━━━━━━━━━━━━━ 18s 45ms/step - accuracy: 0.9168 - loss: 0.2345 - val_accuracy: 0.8760 - val_loss: 0.3988
Epoch 22/50
188/188 ━━━━━━━━━━━━━━━━━━━━ 12s 56ms/step - accuracy: 0.9269 - loss: 0.2103 - val_accuracy: 0.8580 - val_loss: 0.4465
Epoch 23/50
188/188 ━━━━━━━━━━━━━━━━━━━━ 18s 42ms/step - accuracy: 0.9360 - loss: 0.1846 - val_accuracy: 0.7500 - val_loss: 0.8665
Epoch 24/50
188/188 ━━━━━━━━━━━━━━━━━━━━ 11s 56ms/step - accuracy: 0.9409 - loss: 0.1769 - val_accuracy: 0.8190 - val_loss: 0.5828
32/32 ━━━━━━━━━━━━━━━━━━━━ 2s 40ms/step - accuracy: 0.8118 - loss: 0.4407
Test accuracy: 0.812
In [14]:
accuracy = history.history["accuracy"]
val_accuracy = history.history["val_accuracy"]
loss = history.history["loss"]
val_loss = history.history["val_loss"]
epochs = range(1, len(accuracy) + 1)
plt.plot(epochs, accuracy, "bo", label="Training accuracy")
plt.plot(epochs, val_accuracy, "b", label="Validation accuracy")
plt.title("Training and validation accuracy")
plt.legend()
plt.figure()
plt.plot(epochs, loss, "bo", label="Training loss")
plt.plot(epochs, val_loss, "b", label="Validation loss")
plt.title("Training and validation loss")
plt.legend()
plt.show()
  1. Now change your training sample so that you achieve better performance than those from Steps 1 and 2. This sample size may be larger, or smaller than those in the previous steps. The objective is to find the ideal training sample size to get best prediction results.

Now, the third model will have 9000 training samples we will keep the same validation sample of 500, and a test sample of 500.

In [15]:
from tensorflow.keras.utils import image_dataset_from_directory


make_subset("train_3", start_index=0, end_index=9000)
make_subset("validation_3", start_index=9000, end_index=9500)
make_subset("test_3", start_index=9500, end_index=10000)

train_dataset = image_dataset_from_directory(
    new_base_dir / "train_3",
    image_size=(180, 180),
    batch_size=32)
validation_dataset = image_dataset_from_directory(
    new_base_dir / "validation_3",
    image_size=(180, 180),
    batch_size=32)
test_dataset = image_dataset_from_directory(
    new_base_dir / "test_3",
    image_size=(180, 180),
    batch_size=32)
Found 18000 files belonging to 2 classes.
Found 1000 files belonging to 2 classes.
Found 1000 files belonging to 2 classes.
In [17]:
from tensorflow import keras
from tensorflow.keras import layers
import matplotlib.pyplot as plt
from keras.callbacks import EarlyStopping
from keras import regularizers
# Define early_stopping_monitor
# used early stopping to stop optimization when it isn't helping any more.
early_stopping_monitor = EarlyStopping(patience=10)

data_augmentation = keras.Sequential(
    [
        layers.RandomFlip("horizontal"),
        layers.RandomRotation(0.1),
        layers.RandomZoom(0.2),
    ]
)

plt.figure(figsize=(10, 10))
for images, _ in train_dataset.take(1):
    for i in range(9):
        augmented_images = data_augmentation(images)
        ax = plt.subplot(3, 3, i + 1)
        plt.imshow(augmented_images[0].numpy().astype("uint8"))
        plt.axis("off")


inputs = keras.Input(shape=(180, 180, 3))
x = layers.Rescaling(1./255)(inputs)
x = layers.Conv2D(filters=32, kernel_size=3, activation="relu")(x)
x = layers.MaxPooling2D(pool_size=2)(x)
x = layers.Conv2D(filters=64, kernel_size=3, activation="relu")(x)
x = layers.MaxPooling2D(pool_size=2)(x)
x = layers.Conv2D(filters=128, kernel_size=3, activation="relu")(x)
x = layers.MaxPooling2D(pool_size=2)(x)
x = layers.Conv2D(filters=256, kernel_size=3, activation="relu")(x)
x = layers.MaxPooling2D(pool_size=2)(x)
x = layers.Conv2D(filters=256, kernel_size=3, activation="relu", kernel_regularizer=regularizers.l2(0.01))(x)
x = layers.Flatten()(x)
x = layers.Dropout(0.5)(x)
outputs = layers.Dense(1, activation="sigmoid")(x)
model = keras.Model(inputs=inputs, outputs=outputs)
model.summary()


model.compile(loss="binary_crossentropy",
              optimizer=keras.optimizers.RMSprop(learning_rate=1e-3),
              metrics=["accuracy"])


callbacks = [
    keras.callbacks.ModelCheckpoint(
        filepath="convnet_from_scratch.keras",
        save_best_only=True,
        monitor="val_loss"), early_stopping_monitor
]
history = model.fit(
    train_dataset,
    epochs=50,
    validation_data=validation_dataset,
    callbacks=callbacks)




test_model = keras.models.load_model("convnet_from_scratch.keras")
test_loss, test_acc = test_model.evaluate(test_dataset)
print(f"Test accuracy: {test_acc:.3f}")
Model: "functional_8"
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━┓
┃ Layer (type)                         ┃ Output Shape                ┃         Param # ┃
┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━┩
│ input_layer_11 (InputLayer)          │ (None, 180, 180, 3)         │               0 │
├──────────────────────────────────────┼─────────────────────────────┼─────────────────┤
│ rescaling_5 (Rescaling)              │ (None, 180, 180, 3)         │               0 │
├──────────────────────────────────────┼─────────────────────────────┼─────────────────┤
│ conv2d_22 (Conv2D)                   │ (None, 178, 178, 32)        │             896 │
├──────────────────────────────────────┼─────────────────────────────┼─────────────────┤
│ max_pooling2d_20 (MaxPooling2D)      │ (None, 89, 89, 32)          │               0 │
├──────────────────────────────────────┼─────────────────────────────┼─────────────────┤
│ conv2d_23 (Conv2D)                   │ (None, 87, 87, 64)          │          18,496 │
├──────────────────────────────────────┼─────────────────────────────┼─────────────────┤
│ max_pooling2d_21 (MaxPooling2D)      │ (None, 43, 43, 64)          │               0 │
├──────────────────────────────────────┼─────────────────────────────┼─────────────────┤
│ conv2d_24 (Conv2D)                   │ (None, 41, 41, 128)         │          73,856 │
├──────────────────────────────────────┼─────────────────────────────┼─────────────────┤
│ max_pooling2d_22 (MaxPooling2D)      │ (None, 20, 20, 128)         │               0 │
├──────────────────────────────────────┼─────────────────────────────┼─────────────────┤
│ conv2d_25 (Conv2D)                   │ (None, 18, 18, 256)         │         295,168 │
├──────────────────────────────────────┼─────────────────────────────┼─────────────────┤
│ max_pooling2d_23 (MaxPooling2D)      │ (None, 9, 9, 256)           │               0 │
├──────────────────────────────────────┼─────────────────────────────┼─────────────────┤
│ conv2d_26 (Conv2D)                   │ (None, 7, 7, 256)           │         590,080 │
├──────────────────────────────────────┼─────────────────────────────┼─────────────────┤
│ flatten_2 (Flatten)                  │ (None, 12544)               │               0 │
├──────────────────────────────────────┼─────────────────────────────┼─────────────────┤
│ dropout_1 (Dropout)                  │ (None, 12544)               │               0 │
├──────────────────────────────────────┼─────────────────────────────┼─────────────────┤
│ dense_2 (Dense)                      │ (None, 1)                   │          12,545 │
└──────────────────────────────────────┴─────────────────────────────┴─────────────────┘
 Total params: 991,041 (3.78 MB)
 Trainable params: 991,041 (3.78 MB)
 Non-trainable params: 0 (0.00 B)
Epoch 1/50
563/563 ━━━━━━━━━━━━━━━━━━━━ 34s 54ms/step - accuracy: 0.5414 - loss: 0.9275 - val_accuracy: 0.6840 - val_loss: 0.6082
Epoch 2/50
563/563 ━━━━━━━━━━━━━━━━━━━━ 37s 49ms/step - accuracy: 0.6754 - loss: 0.6126 - val_accuracy: 0.6850 - val_loss: 0.5913
Epoch 3/50
563/563 ━━━━━━━━━━━━━━━━━━━━ 40s 47ms/step - accuracy: 0.7275 - loss: 0.5496 - val_accuracy: 0.7630 - val_loss: 0.4997
Epoch 4/50
563/563 ━━━━━━━━━━━━━━━━━━━━ 40s 44ms/step - accuracy: 0.7703 - loss: 0.5002 - val_accuracy: 0.8140 - val_loss: 0.4364
Epoch 5/50
563/563 ━━━━━━━━━━━━━━━━━━━━ 27s 48ms/step - accuracy: 0.7990 - loss: 0.4561 - val_accuracy: 0.8160 - val_loss: 0.4218
Epoch 6/50
563/563 ━━━━━━━━━━━━━━━━━━━━ 40s 46ms/step - accuracy: 0.8256 - loss: 0.4131 - val_accuracy: 0.8320 - val_loss: 0.3800
Epoch 7/50
563/563 ━━━━━━━━━━━━━━━━━━━━ 39s 43ms/step - accuracy: 0.8417 - loss: 0.3805 - val_accuracy: 0.8400 - val_loss: 0.3747
Epoch 8/50
563/563 ━━━━━━━━━━━━━━━━━━━━ 27s 49ms/step - accuracy: 0.8527 - loss: 0.3529 - val_accuracy: 0.8660 - val_loss: 0.3398
Epoch 9/50
563/563 ━━━━━━━━━━━━━━━━━━━━ 25s 44ms/step - accuracy: 0.8717 - loss: 0.3237 - val_accuracy: 0.8930 - val_loss: 0.2908
Epoch 10/50
563/563 ━━━━━━━━━━━━━━━━━━━━ 41s 44ms/step - accuracy: 0.8812 - loss: 0.2988 - val_accuracy: 0.8420 - val_loss: 0.4357
Epoch 11/50
563/563 ━━━━━━━━━━━━━━━━━━━━ 44s 48ms/step - accuracy: 0.8975 - loss: 0.2694 - val_accuracy: 0.8850 - val_loss: 0.2984
Epoch 12/50
563/563 ━━━━━━━━━━━━━━━━━━━━ 41s 49ms/step - accuracy: 0.9002 - loss: 0.2541 - val_accuracy: 0.8970 - val_loss: 0.3370
Epoch 13/50
563/563 ━━━━━━━━━━━━━━━━━━━━ 25s 44ms/step - accuracy: 0.9150 - loss: 0.2346 - val_accuracy: 0.8870 - val_loss: 0.3108
Epoch 14/50
563/563 ━━━━━━━━━━━━━━━━━━━━ 27s 48ms/step - accuracy: 0.9222 - loss: 0.2133 - val_accuracy: 0.8310 - val_loss: 0.5047
Epoch 15/50
563/563 ━━━━━━━━━━━━━━━━━━━━ 26s 45ms/step - accuracy: 0.9244 - loss: 0.2045 - val_accuracy: 0.9110 - val_loss: 0.2770
Epoch 16/50
563/563 ━━━━━━━━━━━━━━━━━━━━ 40s 43ms/step - accuracy: 0.9310 - loss: 0.1947 - val_accuracy: 0.8940 - val_loss: 0.3078
Epoch 17/50
563/563 ━━━━━━━━━━━━━━━━━━━━ 42s 45ms/step - accuracy: 0.9319 - loss: 0.1917 - val_accuracy: 0.9190 - val_loss: 0.2534
Epoch 18/50
563/563 ━━━━━━━━━━━━━━━━━━━━ 27s 47ms/step - accuracy: 0.9413 - loss: 0.1671 - val_accuracy: 0.8540 - val_loss: 0.5537
Epoch 19/50
563/563 ━━━━━━━━━━━━━━━━━━━━ 39s 45ms/step - accuracy: 0.9394 - loss: 0.1880 - val_accuracy: 0.8980 - val_loss: 0.3657
Epoch 20/50
563/563 ━━━━━━━━━━━━━━━━━━━━ 41s 44ms/step - accuracy: 0.9435 - loss: 0.1628 - val_accuracy: 0.9170 - val_loss: 0.2956
Epoch 21/50
563/563 ━━━━━━━━━━━━━━━━━━━━ 27s 49ms/step - accuracy: 0.9462 - loss: 0.1617 - val_accuracy: 0.8840 - val_loss: 0.3211
Epoch 22/50
563/563 ━━━━━━━━━━━━━━━━━━━━ 38s 43ms/step - accuracy: 0.9534 - loss: 0.1485 - val_accuracy: 0.9080 - val_loss: 0.2676
Epoch 23/50
563/563 ━━━━━━━━━━━━━━━━━━━━ 41s 43ms/step - accuracy: 0.9510 - loss: 0.1504 - val_accuracy: 0.8740 - val_loss: 0.3851
Epoch 24/50
563/563 ━━━━━━━━━━━━━━━━━━━━ 43s 47ms/step - accuracy: 0.9556 - loss: 0.1407 - val_accuracy: 0.8960 - val_loss: 0.3337
Epoch 25/50
563/563 ━━━━━━━━━━━━━━━━━━━━ 42s 48ms/step - accuracy: 0.9600 - loss: 0.1280 - val_accuracy: 0.9050 - val_loss: 0.3987
Epoch 26/50
563/563 ━━━━━━━━━━━━━━━━━━━━ 39s 44ms/step - accuracy: 0.9567 - loss: 0.1336 - val_accuracy: 0.9160 - val_loss: 0.3582
Epoch 27/50
563/563 ━━━━━━━━━━━━━━━━━━━━ 41s 44ms/step - accuracy: 0.9595 - loss: 0.1358 - val_accuracy: 0.9120 - val_loss: 0.3532
32/32 ━━━━━━━━━━━━━━━━━━━━ 2s 45ms/step - accuracy: 0.8873 - loss: 0.3022
Test accuracy: 0.896
In [18]:
accuracy = history.history["accuracy"]
val_accuracy = history.history["val_accuracy"]
loss = history.history["loss"]
val_loss = history.history["val_loss"]
epochs = range(1, len(accuracy) + 1)
plt.plot(epochs, accuracy, "bo", label="Training accuracy")
plt.plot(epochs, val_accuracy, "b", label="Validation accuracy")
plt.title("Training and validation accuracy")
plt.legend()
plt.figure()
plt.plot(epochs, loss, "bo", label="Training loss")
plt.plot(epochs, val_loss, "b", label="Validation loss")
plt.title("Training and validation loss")
plt.legend()
plt.show()
  1. Repeat Steps 1-3, but now using a pretrained network. The sample sizes you use in Steps 2 and 3 for the pretrained network may be the same or different from those using the network where you trained from scratch. Again, use any and all optimization techniques to get best performance.

Pretrained Model 1 : Training sample of 2000, a validation sample of 1000, and a test sample of 1000.

VGG16 Pretrained Convnet Network

Using Feature Extraction with Data Augmentation and Fine-tuning

In [19]:
import matplotlib.pyplot as plt
from tensorflow import keras
from tensorflow.keras import layers

# Instantiating the VGG16 convolutional base
conv_base  = keras.applications.vgg16.VGG16(
    weights="imagenet",
    include_top=False)

# Freezing all layers until the fourth from the last
conv_base.trainable = True
for layer in conv_base.layers[:-4]:
    layer.trainable = False

# Adding a data augmentation stage and a classifier to the convolutional base
data_augmentation = keras.Sequential(
    [
        layers.RandomFlip("horizontal"),
        layers.RandomRotation(0.1),
        layers.RandomZoom(0.2),
    ]
)

inputs = keras.Input(shape=(180, 180, 3))
x = data_augmentation(inputs)
x = keras.applications.vgg16.preprocess_input(x)
x = conv_base(x)
x = layers.Flatten()(x)
x = layers.Dense(256)(x)
x = layers.Dropout(0.5)(x)
outputs = layers.Dense(1, activation="sigmoid")(x)
model_pre_trained_1 = keras.Model(inputs, outputs)
# Fine-tuning the model
model_pre_trained_1.compile(loss="binary_crossentropy",
              optimizer=keras.optimizers.RMSprop(learning_rate=1e-6),
              metrics=["accuracy"])


# Used early stopping to stop optimization
early_stopping_monitor = EarlyStopping(patience=10)


callbacks = [
    keras.callbacks.ModelCheckpoint(
        filepath="convnet_from_scratch.keras",
        save_best_only=True,
        monitor="val_loss"), early_stopping_monitor
]
history = model.fit(
    train_dataset,
    epochs=50,
    validation_data=validation_dataset,
    callbacks=callbacks)

plt.figure(figsize=(10, 10))
for images, _ in train_dataset.take(1):
    for i in range(9):
        augmented_images = data_augmentation(images)
        ax = plt.subplot(3, 3, i + 1)
        plt.imshow(augmented_images[0].numpy().astype("uint8"))
        plt.axis("off")

plt.show()

test_model = keras.models.load_model("convnet_from_scratch.keras")
test_loss, test_acc = test_model.evaluate(test_dataset)
print(f"Test accuracy: {test_acc:.3f}")
Downloading data from https://storage.googleapis.com/tensorflow/keras-applications/vgg16/vgg16_weights_tf_dim_ordering_tf_kernels_notop.h5
58889256/58889256 ━━━━━━━━━━━━━━━━━━━━ 0s 0us/step
Epoch 1/50
563/563 ━━━━━━━━━━━━━━━━━━━━ 28s 49ms/step - accuracy: 0.9561 - loss: 0.1402 - val_accuracy: 0.8800 - val_loss: 0.4756
Epoch 2/50
563/563 ━━━━━━━━━━━━━━━━━━━━ 38s 43ms/step - accuracy: 0.9565 - loss: 0.1520 - val_accuracy: 0.9080 - val_loss: 0.3930
Epoch 3/50
563/563 ━━━━━━━━━━━━━━━━━━━━ 27s 48ms/step - accuracy: 0.9599 - loss: 0.1313 - val_accuracy: 0.8920 - val_loss: 0.4743
Epoch 4/50
563/563 ━━━━━━━━━━━━━━━━━━━━ 39s 45ms/step - accuracy: 0.9618 - loss: 0.1313 - val_accuracy: 0.9000 - val_loss: 0.4542
Epoch 5/50
563/563 ━━━━━━━━━━━━━━━━━━━━ 26s 46ms/step - accuracy: 0.9625 - loss: 0.1256 - val_accuracy: 0.8950 - val_loss: 0.3894
Epoch 6/50
563/563 ━━━━━━━━━━━━━━━━━━━━ 42s 48ms/step - accuracy: 0.9587 - loss: 0.1380 - val_accuracy: 0.9100 - val_loss: 0.2933
Epoch 7/50
563/563 ━━━━━━━━━━━━━━━━━━━━ 25s 44ms/step - accuracy: 0.9659 - loss: 0.1242 - val_accuracy: 0.9040 - val_loss: 0.4461
Epoch 8/50
563/563 ━━━━━━━━━━━━━━━━━━━━ 42s 45ms/step - accuracy: 0.9621 - loss: 0.1268 - val_accuracy: 0.8820 - val_loss: 0.4899
Epoch 9/50
563/563 ━━━━━━━━━━━━━━━━━━━━ 42s 47ms/step - accuracy: 0.9631 - loss: 0.1363 - val_accuracy: 0.8720 - val_loss: 0.8799
Epoch 10/50
563/563 ━━━━━━━━━━━━━━━━━━━━ 41s 48ms/step - accuracy: 0.9651 - loss: 0.1281 - val_accuracy: 0.8950 - val_loss: 0.3202
Epoch 11/50
563/563 ━━━━━━━━━━━━━━━━━━━━ 38s 43ms/step - accuracy: 0.9662 - loss: 0.1312 - val_accuracy: 0.9000 - val_loss: 0.3921
Epoch 12/50
563/563 ━━━━━━━━━━━━━━━━━━━━ 42s 45ms/step - accuracy: 0.9601 - loss: 0.1477 - val_accuracy: 0.9000 - val_loss: 0.4189
Epoch 13/50
563/563 ━━━━━━━━━━━━━━━━━━━━ 43s 49ms/step - accuracy: 0.9639 - loss: 0.1236 - val_accuracy: 0.8190 - val_loss: 1.4806
Epoch 14/50
563/563 ━━━━━━━━━━━━━━━━━━━━ 26s 47ms/step - accuracy: 0.9669 - loss: 0.1274 - val_accuracy: 0.9220 - val_loss: 0.3507
Epoch 15/50
563/563 ━━━━━━━━━━━━━━━━━━━━ 39s 44ms/step - accuracy: 0.9679 - loss: 0.1281 - val_accuracy: 0.9040 - val_loss: 0.4525
Epoch 16/50
563/563 ━━━━━━━━━━━━━━━━━━━━ 43s 47ms/step - accuracy: 0.9675 - loss: 0.1240 - val_accuracy: 0.8790 - val_loss: 0.4057
32/32 ━━━━━━━━━━━━━━━━━━━━ 2s 44ms/step - accuracy: 0.9290 - loss: 0.2517
Test accuracy: 0.916
In [20]:
# Plotting the results
accuracy = history.history["accuracy"]
val_accuracy = history.history["val_accuracy"]
loss = history.history["loss"]
val_loss = history.history["val_loss"]
epochs = range(1, len(accuracy) + 1)
plt.plot(epochs, accuracy, "bo", label="Training accuracy")
plt.plot(epochs, val_accuracy, "b", label="Validation accuracy")
plt.title("Training and validation accuracy")
plt.legend()
plt.figure()
plt.plot(epochs, loss, "bo", label="Training loss")
plt.plot(epochs, val_loss, "b", label="Validation loss")
plt.title("Training and validation loss")
plt.legend()
plt.show()

Pretrained Model 2: ResNet50V2 convolutional base

In [21]:
import os
import shutil
import pathlib
import tensorflow as tf
from tensorflow.keras import layers
from tensorflow.keras.models import Sequential
from tensorflow.keras.callbacks import ModelCheckpoint

original_dir = pathlib.Path("train")
new_base_dir = pathlib.Path("cats_vs_dogs_small_3")

def make_subset(subset_name, start_index, end_index):
    for category in ("cat", "dog"):
        dir = new_base_dir / subset_name / category
        os.makedirs(dir, exist_ok=True)
        fnames = [f"{category}.{i}.jpg" for i in range(start_index, end_index)]
        for fname in fnames:
            shutil.copyfile(src=original_dir / fname, dst=dir / fname)

make_subset("validation", start_index=0, end_index=500)
make_subset("test", start_index=500, end_index=1000)
make_subset("train", start_index=1000, end_index=5000)

train_dataset = tf.keras.utils.image_dataset_from_directory(
    new_base_dir / "train",
    image_size=(180, 180),
    batch_size=32)
validation_dataset = tf.keras.utils.image_dataset_from_directory(
    new_base_dir / "validation",
    image_size=(180, 180),
    batch_size=32)
test_dataset = tf.keras.utils.image_dataset_from_directory(
    new_base_dir / "test",
    image_size=(180, 180),
    batch_size=32)

model = Sequential([
    layers.Conv2D(32, (3, 3), activation='relu', input_shape=(180, 180, 3)),
    layers.MaxPooling2D((2, 2)),
    layers.Conv2D(64, (3, 3), activation='relu'),
    layers.MaxPooling2D((2, 2)),
    layers.Conv2D(128, (3, 3), activation='relu'),
    layers.MaxPooling2D((2, 2)),
    layers.Conv2D(128, (3, 3), activation='relu'),
    layers.MaxPooling2D((2, 2)),
    layers.Flatten(),
    layers.Dense(512, activation='relu'),
    layers.Dense(1, activation='sigmoid')
])

model.compile(optimizer='adam',
              loss='binary_crossentropy',
              metrics=['accuracy'])

callbacks = [
    ModelCheckpoint(
        filepath="convnet_from_scratch_with_augmentation_4000.keras",
        save_best_only=True,
        monitor="val_loss")
]

history = model.fit(
    train_dataset,
    epochs=20,
    validation_data=validation_dataset,
    callbacks=callbacks)
Found 8000 files belonging to 2 classes.
Found 1000 files belonging to 2 classes.
Found 1000 files belonging to 2 classes.
Epoch 1/20
/usr/local/lib/python3.10/dist-packages/keras/src/layers/convolutional/base_conv.py:107: UserWarning: Do not pass an `input_shape`/`input_dim` argument to a layer. When using Sequential models, prefer using an `Input(shape)` object as the first layer in the model instead.
  super().__init__(activity_regularizer=activity_regularizer, **kwargs)
250/250 ━━━━━━━━━━━━━━━━━━━━ 20s 59ms/step - accuracy: 0.5465 - loss: 14.0708 - val_accuracy: 0.5340 - val_loss: 0.7383
Epoch 2/20
250/250 ━━━━━━━━━━━━━━━━━━━━ 12s 50ms/step - accuracy: 0.6005 - loss: 0.6607 - val_accuracy: 0.6330 - val_loss: 0.6335
Epoch 3/20
250/250 ━━━━━━━━━━━━━━━━━━━━ 11s 43ms/step - accuracy: 0.6366 - loss: 0.6237 - val_accuracy: 0.6200 - val_loss: 0.6634
Epoch 4/20
250/250 ━━━━━━━━━━━━━━━━━━━━ 23s 52ms/step - accuracy: 0.6644 - loss: 0.6047 - val_accuracy: 0.6880 - val_loss: 0.5736
Epoch 5/20
250/250 ━━━━━━━━━━━━━━━━━━━━ 12s 47ms/step - accuracy: 0.6993 - loss: 0.5638 - val_accuracy: 0.7570 - val_loss: 0.5193
Epoch 6/20
250/250 ━━━━━━━━━━━━━━━━━━━━ 21s 51ms/step - accuracy: 0.7364 - loss: 0.5249 - val_accuracy: 0.6960 - val_loss: 0.6820
Epoch 7/20
250/250 ━━━━━━━━━━━━━━━━━━━━ 20s 49ms/step - accuracy: 0.7763 - loss: 0.4711 - val_accuracy: 0.7350 - val_loss: 0.5486
Epoch 8/20
250/250 ━━━━━━━━━━━━━━━━━━━━ 13s 51ms/step - accuracy: 0.8005 - loss: 0.4272 - val_accuracy: 0.7570 - val_loss: 0.6025
Epoch 9/20
250/250 ━━━━━━━━━━━━━━━━━━━━ 19s 44ms/step - accuracy: 0.8313 - loss: 0.3723 - val_accuracy: 0.7610 - val_loss: 0.6047
Epoch 10/20
250/250 ━━━━━━━━━━━━━━━━━━━━ 22s 50ms/step - accuracy: 0.8706 - loss: 0.2950 - val_accuracy: 0.7800 - val_loss: 0.6965
Epoch 11/20
250/250 ━━━━━━━━━━━━━━━━━━━━ 11s 44ms/step - accuracy: 0.8850 - loss: 0.2651 - val_accuracy: 0.7290 - val_loss: 0.8570
Epoch 12/20
250/250 ━━━━━━━━━━━━━━━━━━━━ 12s 48ms/step - accuracy: 0.8908 - loss: 0.2645 - val_accuracy: 0.7590 - val_loss: 1.0589
Epoch 13/20
250/250 ━━━━━━━━━━━━━━━━━━━━ 22s 52ms/step - accuracy: 0.9150 - loss: 0.2105 - val_accuracy: 0.7690 - val_loss: 1.1091
Epoch 14/20
250/250 ━━━━━━━━━━━━━━━━━━━━ 20s 50ms/step - accuracy: 0.9307 - loss: 0.1823 - val_accuracy: 0.7240 - val_loss: 1.3294
Epoch 15/20
250/250 ━━━━━━━━━━━━━━━━━━━━ 19s 46ms/step - accuracy: 0.9337 - loss: 0.1812 - val_accuracy: 0.7550 - val_loss: 1.1651
Epoch 16/20
250/250 ━━━━━━━━━━━━━━━━━━━━ 13s 52ms/step - accuracy: 0.9459 - loss: 0.1443 - val_accuracy: 0.7620 - val_loss: 1.0986
Epoch 17/20
250/250 ━━━━━━━━━━━━━━━━━━━━ 18s 40ms/step - accuracy: 0.9579 - loss: 0.1118 - val_accuracy: 0.7790 - val_loss: 1.1768
Epoch 18/20
250/250 ━━━━━━━━━━━━━━━━━━━━ 12s 50ms/step - accuracy: 0.9598 - loss: 0.1149 - val_accuracy: 0.7550 - val_loss: 1.2145
Epoch 19/20
250/250 ━━━━━━━━━━━━━━━━━━━━ 13s 50ms/step - accuracy: 0.9659 - loss: 0.1062 - val_accuracy: 0.7620 - val_loss: 1.5361
Epoch 20/20
250/250 ━━━━━━━━━━━━━━━━━━━━ 12s 48ms/step - accuracy: 0.9615 - loss: 0.1139 - val_accuracy: 0.7450 - val_loss: 1.2741
In [22]:
# Plotting the results
accuracy = history.history["accuracy"]
val_accuracy = history.history["val_accuracy"]
loss = history.history["loss"]
val_loss = history.history["val_loss"]
epochs = range(1, len(accuracy) + 1)
plt.plot(epochs, accuracy, "bo", label="Training accuracy")
plt.plot(epochs, val_accuracy, "b", label="Validation accuracy")
plt.title("Training and validation accuracy")
plt.legend()
plt.figure()
plt.plot(epochs, loss, "bo", label="Training loss")
plt.plot(epochs, val_loss, "b", label="Validation loss")
plt.title("Training and validation loss")
plt.legend()
plt.show()

Pretrained Model 3: MobileNetV2

In [25]:
import matplotlib.pyplot as plt
from tensorflow import keras
from tensorflow.keras import layers

# Instantiating the MobileNetV2 convolutional base
conv_base  = keras.applications.MobileNetV2(
    weights="imagenet",
    include_top=False)

# Freezing all layers until fourth from the last
conv_base.trainable = True
for layer in conv_base.layers[:-4]:
    layer.trainable = False

# Adding a data augmentation stage and a classifier to the convolutional base
data_augmentation = keras.Sequential(
    [
        layers.RandomFlip("horizontal"),
        layers.RandomRotation(0.1),
        layers.RandomZoom(0.2),
    ]
)

inputs = keras.Input(shape=(180, 180, 3))
x = data_augmentation(inputs)
x = keras.applications.mobilenet_v2.preprocess_input(x)
x = conv_base(x)
x = layers.GlobalAveragePooling2D()(x)
x = layers.Dense(256)(x)
x = layers.Dropout(0.5)(x)
outputs = layers.Dense(1, activation="sigmoid")(x)
model_pre_trained_2 = keras.Model(inputs, outputs)

# Fine-tuning the model
model_pre_trained_2.compile(loss="binary_crossentropy",
              optimizer=keras.optimizers.RMSprop(learning_rate=1e-6),
              metrics=["accuracy"])

# Used early stopping to stop optimization
early_stopping_monitor = EarlyStopping(patience=10)


callbacks = [
    keras.callbacks.ModelCheckpoint(
        filepath="convnet_from_scratch_2.keras",
        save_best_only=True,
        monitor="val_loss"), early_stopping_monitor
]
history = model_pre_trained_2.fit(
    train_dataset,
    epochs=50,
    validation_data=validation_dataset,
    callbacks=callbacks)

plt.figure(figsize=(10, 10))
for images, _ in train_dataset.take(1):
    for i in range(9):
        augmented_images = data_augmentation(images)
        ax = plt.subplot(3, 3, i + 1)
        plt.imshow(augmented_images[0].numpy().astype("uint8"))
        plt.axis("off")

plt.show()


# Evaluate the model on the test set

test_model = keras.models.load_model("convnet_from_scratch_2.keras")
test_loss, test_acc = test_model.evaluate(test_dataset)
print(f"Test accuracy: {test_acc:.3f}")
<ipython-input-25-f9dfafc74a43>:6: UserWarning: `input_shape` is undefined or non-square, or `rows` is not in [96, 128, 160, 192, 224]. Weights for input shape (224, 224) will be loaded as the default.
  conv_base  = keras.applications.MobileNetV2(
Epoch 1/50
250/250 ━━━━━━━━━━━━━━━━━━━━ 20s 61ms/step - accuracy: 0.6678 - loss: 0.6669 - val_accuracy: 0.8950 - val_loss: 0.2523
Epoch 2/50
250/250 ━━━━━━━━━━━━━━━━━━━━ 19s 54ms/step - accuracy: 0.8027 - loss: 0.4663 - val_accuracy: 0.9370 - val_loss: 0.1773
Epoch 3/50
250/250 ━━━━━━━━━━━━━━━━━━━━ 14s 55ms/step - accuracy: 0.8527 - loss: 0.3647 - val_accuracy: 0.9480 - val_loss: 0.1398
Epoch 4/50
250/250 ━━━━━━━━━━━━━━━━━━━━ 14s 56ms/step - accuracy: 0.8740 - loss: 0.3215 - val_accuracy: 0.9550 - val_loss: 0.1189
Epoch 5/50
250/250 ━━━━━━━━━━━━━━━━━━━━ 13s 53ms/step - accuracy: 0.8980 - loss: 0.2510 - val_accuracy: 0.9590 - val_loss: 0.1049
Epoch 6/50
250/250 ━━━━━━━━━━━━━━━━━━━━ 12s 48ms/step - accuracy: 0.9011 - loss: 0.2512 - val_accuracy: 0.9610 - val_loss: 0.0954
Epoch 7/50
250/250 ━━━━━━━━━━━━━━━━━━━━ 13s 51ms/step - accuracy: 0.9143 - loss: 0.2155 - val_accuracy: 0.9650 - val_loss: 0.0884
Epoch 8/50
250/250 ━━━━━━━━━━━━━━━━━━━━ 21s 54ms/step - accuracy: 0.9260 - loss: 0.2024 - val_accuracy: 0.9710 - val_loss: 0.0830
Epoch 9/50
250/250 ━━━━━━━━━━━━━━━━━━━━ 13s 51ms/step - accuracy: 0.9251 - loss: 0.1935 - val_accuracy: 0.9730 - val_loss: 0.0790
Epoch 10/50
250/250 ━━━━━━━━━━━━━━━━━━━━ 25s 70ms/step - accuracy: 0.9334 - loss: 0.1858 - val_accuracy: 0.9740 - val_loss: 0.0749
Epoch 11/50
250/250 ━━━━━━━━━━━━━━━━━━━━ 16s 54ms/step - accuracy: 0.9372 - loss: 0.1733 - val_accuracy: 0.9760 - val_loss: 0.0718
Epoch 12/50
250/250 ━━━━━━━━━━━━━━━━━━━━ 14s 55ms/step - accuracy: 0.9389 - loss: 0.1612 - val_accuracy: 0.9790 - val_loss: 0.0693
Epoch 13/50
250/250 ━━━━━━━━━━━━━━━━━━━━ 19s 49ms/step - accuracy: 0.9395 - loss: 0.1574 - val_accuracy: 0.9820 - val_loss: 0.0671
Epoch 14/50
250/250 ━━━━━━━━━━━━━━━━━━━━ 14s 56ms/step - accuracy: 0.9418 - loss: 0.1611 - val_accuracy: 0.9820 - val_loss: 0.0652
Epoch 15/50
250/250 ━━━━━━━━━━━━━━━━━━━━ 14s 56ms/step - accuracy: 0.9421 - loss: 0.1591 - val_accuracy: 0.9820 - val_loss: 0.0632
Epoch 16/50
250/250 ━━━━━━━━━━━━━━━━━━━━ 14s 55ms/step - accuracy: 0.9418 - loss: 0.1593 - val_accuracy: 0.9820 - val_loss: 0.0617
Epoch 17/50
250/250 ━━━━━━━━━━━━━━━━━━━━ 20s 55ms/step - accuracy: 0.9419 - loss: 0.1566 - val_accuracy: 0.9830 - val_loss: 0.0602
Epoch 18/50
250/250 ━━━━━━━━━━━━━━━━━━━━ 18s 47ms/step - accuracy: 0.9452 - loss: 0.1433 - val_accuracy: 0.9830 - val_loss: 0.0591
Epoch 19/50
250/250 ━━━━━━━━━━━━━━━━━━━━ 22s 55ms/step - accuracy: 0.9446 - loss: 0.1493 - val_accuracy: 0.9840 - val_loss: 0.0580
Epoch 20/50
250/250 ━━━━━━━━━━━━━━━━━━━━ 14s 54ms/step - accuracy: 0.9481 - loss: 0.1388 - val_accuracy: 0.9840 - val_loss: 0.0566
Epoch 21/50
250/250 ━━━━━━━━━━━━━━━━━━━━ 12s 49ms/step - accuracy: 0.9494 - loss: 0.1426 - val_accuracy: 0.9830 - val_loss: 0.0556
Epoch 22/50
250/250 ━━━━━━━━━━━━━━━━━━━━ 13s 50ms/step - accuracy: 0.9431 - loss: 0.1418 - val_accuracy: 0.9830 - val_loss: 0.0545
Epoch 23/50
250/250 ━━━━━━━━━━━━━━━━━━━━ 14s 56ms/step - accuracy: 0.9474 - loss: 0.1404 - val_accuracy: 0.9830 - val_loss: 0.0539
Epoch 24/50
250/250 ━━━━━━━━━━━━━━━━━━━━ 19s 49ms/step - accuracy: 0.9474 - loss: 0.1469 - val_accuracy: 0.9830 - val_loss: 0.0531
Epoch 25/50
250/250 ━━━━━━━━━━━━━━━━━━━━ 12s 49ms/step - accuracy: 0.9460 - loss: 0.1487 - val_accuracy: 0.9830 - val_loss: 0.0529
Epoch 26/50
250/250 ━━━━━━━━━━━━━━━━━━━━ 22s 55ms/step - accuracy: 0.9522 - loss: 0.1292 - val_accuracy: 0.9830 - val_loss: 0.0526
Epoch 27/50
250/250 ━━━━━━━━━━━━━━━━━━━━ 21s 55ms/step - accuracy: 0.9485 - loss: 0.1341 - val_accuracy: 0.9830 - val_loss: 0.0519
Epoch 28/50
250/250 ━━━━━━━━━━━━━━━━━━━━ 18s 47ms/step - accuracy: 0.9519 - loss: 0.1291 - val_accuracy: 0.9830 - val_loss: 0.0515
Epoch 29/50
250/250 ━━━━━━━━━━━━━━━━━━━━ 22s 55ms/step - accuracy: 0.9528 - loss: 0.1394 - val_accuracy: 0.9830 - val_loss: 0.0505
Epoch 30/50
250/250 ━━━━━━━━━━━━━━━━━━━━ 14s 54ms/step - accuracy: 0.9513 - loss: 0.1305 - val_accuracy: 0.9830 - val_loss: 0.0499
Epoch 31/50
250/250 ━━━━━━━━━━━━━━━━━━━━ 21s 55ms/step - accuracy: 0.9513 - loss: 0.1361 - val_accuracy: 0.9830 - val_loss: 0.0493
Epoch 32/50
250/250 ━━━━━━━━━━━━━━━━━━━━ 14s 55ms/step - accuracy: 0.9544 - loss: 0.1273 - val_accuracy: 0.9830 - val_loss: 0.0489
Epoch 33/50
250/250 ━━━━━━━━━━━━━━━━━━━━ 12s 50ms/step - accuracy: 0.9466 - loss: 0.1385 - val_accuracy: 0.9830 - val_loss: 0.0492
Epoch 34/50
250/250 ━━━━━━━━━━━━━━━━━━━━ 12s 46ms/step - accuracy: 0.9529 - loss: 0.1300 - val_accuracy: 0.9830 - val_loss: 0.0485
Epoch 35/50
250/250 ━━━━━━━━━━━━━━━━━━━━ 14s 54ms/step - accuracy: 0.9540 - loss: 0.1308 - val_accuracy: 0.9830 - val_loss: 0.0481
Epoch 36/50
250/250 ━━━━━━━━━━━━━━━━━━━━ 13s 53ms/step - accuracy: 0.9618 - loss: 0.1133 - val_accuracy: 0.9830 - val_loss: 0.0481
Epoch 37/50
250/250 ━━━━━━━━━━━━━━━━━━━━ 19s 48ms/step - accuracy: 0.9562 - loss: 0.1190 - val_accuracy: 0.9830 - val_loss: 0.0480
Epoch 38/50
250/250 ━━━━━━━━━━━━━━━━━━━━ 22s 55ms/step - accuracy: 0.9572 - loss: 0.1145 - val_accuracy: 0.9830 - val_loss: 0.0477
Epoch 39/50
250/250 ━━━━━━━━━━━━━━━━━━━━ 14s 56ms/step - accuracy: 0.9537 - loss: 0.1186 - val_accuracy: 0.9830 - val_loss: 0.0473
Epoch 40/50
250/250 ━━━━━━━━━━━━━━━━━━━━ 13s 51ms/step - accuracy: 0.9521 - loss: 0.1294 - val_accuracy: 0.9830 - val_loss: 0.0467
Epoch 41/50
250/250 ━━━━━━━━━━━━━━━━━━━━ 22s 55ms/step - accuracy: 0.9569 - loss: 0.1239 - val_accuracy: 0.9830 - val_loss: 0.0460
Epoch 42/50
250/250 ━━━━━━━━━━━━━━━━━━━━ 15s 59ms/step - accuracy: 0.9569 - loss: 0.1149 - val_accuracy: 0.9830 - val_loss: 0.0459
Epoch 43/50
250/250 ━━━━━━━━━━━━━━━━━━━━ 13s 53ms/step - accuracy: 0.9556 - loss: 0.1219 - val_accuracy: 0.9830 - val_loss: 0.0459
Epoch 44/50
250/250 ━━━━━━━━━━━━━━━━━━━━ 12s 49ms/step - accuracy: 0.9565 - loss: 0.1223 - val_accuracy: 0.9840 - val_loss: 0.0460
Epoch 45/50
250/250 ━━━━━━━━━━━━━━━━━━━━ 12s 49ms/step - accuracy: 0.9605 - loss: 0.1079 - val_accuracy: 0.9840 - val_loss: 0.0457
Epoch 46/50
250/250 ━━━━━━━━━━━━━━━━━━━━ 14s 55ms/step - accuracy: 0.9582 - loss: 0.1206 - val_accuracy: 0.9840 - val_loss: 0.0451
Epoch 47/50
250/250 ━━━━━━━━━━━━━━━━━━━━ 18s 44ms/step - accuracy: 0.9516 - loss: 0.1286 - val_accuracy: 0.9840 - val_loss: 0.0452
Epoch 48/50
250/250 ━━━━━━━━━━━━━━━━━━━━ 13s 53ms/step - accuracy: 0.9525 - loss: 0.1302 - val_accuracy: 0.9840 - val_loss: 0.0452
Epoch 49/50
250/250 ━━━━━━━━━━━━━━━━━━━━ 14s 54ms/step - accuracy: 0.9608 - loss: 0.1100 - val_accuracy: 0.9840 - val_loss: 0.0456
Epoch 50/50
250/250 ━━━━━━━━━━━━━━━━━━━━ 13s 54ms/step - accuracy: 0.9566 - loss: 0.1230 - val_accuracy: 0.9840 - val_loss: 0.0453
32/32 ━━━━━━━━━━━━━━━━━━━━ 5s 67ms/step - accuracy: 0.9729 - loss: 0.0547
Test accuracy: 0.981
In [26]:
# Plotting the results
accuracy = history.history["accuracy"]
val_accuracy = history.history["val_accuracy"]
loss = history.history["loss"]
val_loss = history.history["val_loss"]
epochs = range(1, len(accuracy) + 1)
plt.plot(epochs, accuracy, "bo", label="Training accuracy")
plt.plot(epochs, val_accuracy, "b", label="Validation accuracy")
plt.title("Training and validation accuracy")
plt.legend()
plt.figure()
plt.plot(epochs, loss, "bo", label="Training loss")
plt.plot(epochs, val_loss, "b", label="Validation loss")
plt.title("Training and validation loss")
plt.legend()
plt.show()